
package com.quartet.modules.security.rest;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.quartet.annotation.rest.AnonymousDeleteMapping;
import com.quartet.annotation.rest.AnonymousPostMapping;
import com.quartet.api.ApiResult;
import com.quartet.modules.order.service.TOrderService;
import com.quartet.modules.security.config.bean.LoginCodeEnum;
import com.quartet.modules.security.config.bean.LoginProperties;
import com.quartet.modules.security.config.bean.SecurityProperties;
import com.quartet.modules.security.security.TokenProvider;
import com.quartet.modules.security.service.OnlineUserService;
import com.quartet.modules.security.service.dto.AuthUserDto;
import com.quartet.modules.security.service.dto.JwtUserDto;
import com.quartet.modules.system.service.RoleService;
import com.quartet.modules.system.service.dto.RoleDto;
import com.quartet.modules.user.entity.TUserInfo;
import com.quartet.modules.user.service.TUserInfoService;
import com.quartet.utils.RedisUtils;
import com.quartet.utils.SecurityUtils;
import com.quartet.utils.StringUtils;
import com.wf.captcha.base.Captcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.quartet.annotation.rest.AnonymousGetMapping;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Zheng Jie
 * @date 2018-11-23
 * 授权、根据token获取用户详细信息
 */
@Slf4j
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
@Api(tags = "系统：系统授权接口")
public class AuthorizationController {
    private final SecurityProperties properties;
    private final RedisUtils redisUtils;
    private final OnlineUserService onlineUserService;
    private final TokenProvider tokenProvider;
    private final AuthenticationManagerBuilder authenticationManagerBuilder;
    @Resource
    private LoginProperties loginProperties;
    @Resource
    private TUserInfoService tUserInfoService;
    @Resource
    private TOrderService tOrderService;
    @Resource
    private RoleService roleService;

    @ApiOperation("登录授权")
    @AnonymousPostMapping(value = "/login")
    public ApiResult<Map> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
        // 密码解密
//        String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
        String password = authUser.getPassword();
        // 查询验证码
//        String code = (String) redisUtils.get(authUser.getUuid());
//        // 清除验证码
//        redisUtils.del(authUser.getUuid());
//        if (StringUtils.isBlank(code)) {
//            throw new BadRequestException("验证码不存在或已过期");
//        }
//        if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {
//            throw new BadRequestException("验证码错误");
//        }
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        // 生成令牌与第三方系统获取令牌方式
        // UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername());
        // Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        // SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = tokenProvider.createToken(authentication);
        final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
        // 保存在线信息
//        onlineUserService.save(jwtUserDto, token, request);
        // 返回 token 与 用户信息

        QueryWrapper<TUserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TUserInfo::getUsername, authUser.getUsername());
        TUserInfo tUserInfo = tUserInfoService.getOne(queryWrapper);

        RoleDto roleDto = roleService.findById(Long.parseLong(tUserInfo.getRoleId()));

//        TOrder tOrder = tOrderService.getOne(new QueryWrapper<TOrder>().lambda().eq(TOrder::getCustomerCode, tUserInfo.getCustomerCode()).eq(TOrder::getOrderCode, tUserInfo.getOrderCode()));

        Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
            put("token", properties.getTokenStartWith() + token);
            put("user1", jwtUserDto);
            put("roleDto", roleDto);
            put("customerCode", StringUtils.isBlank(tUserInfo.getCustomerCode()) ? "admin" : tUserInfo.getCustomerCode());
        }};
//        if (loginProperties.isSingleLogin()) {
//            //踢掉之前已经登录的token
//            onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
//        }
        //查询出客户的订单key返回给前端
        return ApiResult.ok(authInfo);
    }

    @ApiOperation("获取用户信息")
    @GetMapping(value = "/info")
    public ApiResult<UserDetails> getUserInfo() {
        return ApiResult.ok(SecurityUtils.getCurrentUser());
    }

    @ApiOperation("获取验证码")
    @AnonymousGetMapping(value = "/code")
    public ApiResult<Object> getCode() {
        // 获取运算的结果
        Captcha captcha = loginProperties.getCaptcha();
        String uuid = properties.getCodeKey() + IdUtil.simpleUUID();
        //当验证码类型为 arithmetic时且长度 >= 2 时，captcha.text()的结果有几率为浮点型
        String captchaValue = captcha.text();
        if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(".")) {
            captchaValue = captchaValue.split("\\.")[0];
        }
        // 保存
        redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
        // 验证码信息
        Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
            put("img", captcha.toBase64());
            put("uuid", uuid);
        }};
        return ApiResult.ok(imgResult);
    }

    @ApiOperation("退出登录")
    @AnonymousDeleteMapping(value = "/logout")
    public ApiResult logout(HttpServletRequest request) {
//        onlineUserService.logout(tokenProvider.getToken(request));
        request.getSession().invalidate();
        return ApiResult.ok();
    }
}
